package com.sunday.common.netty.e4_TCP.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.Scanner;

@Slf4j
@AllArgsConstructor
public class TcpClient {

    public static final String SERVER_HOST = "localhost";
    public static final int SERVER_PORT = 8811;

    public static void main(String[] args) throws Exception {
        /**
         * Bootstrap: 用于客户端，连接到远程主机和端口，1个EventLoopGroup
         */
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap()
                    .group(workerGroup)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new TcpClientChannel());
            ChannelFuture channelFuture = bootstrap.connect(SERVER_HOST, SERVER_PORT).sync();
            log.info("Client started.");

            log.info("Input message: ");

            while (true) {
                Scanner reader = new Scanner(System.in);
                String input = reader.nextLine();
                if ("quit".equalsIgnoreCase(input)) {
                    break;
                }
                channelFuture.channel().writeAndFlush(input);
            }
            /**
             * channelFuture.channel().close() 是立即关闭通道，它会立即执行关闭动作而不会阻塞当前线程。
             * channelFuture.channel().closeFuture().sync() 是等待通道关闭的 Future 完成。这会阻塞当前线程直到通道关闭。
             * 虽然在某些情况下两者可能达到相似的效果，但不能完全互相替代。前者是直接关闭通道，而后者是用于在关闭操作完成后执行其他任务或等待关闭操作完成。
             */
            // channelFuture.channel().close() 会触发 channelInactive() 事件。
            channelFuture.channel().close();
            // channelFuture.channel().closeFuture().sync() 会触发 channelUnregistered() 事件。
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            workerGroup.shutdownGracefully();
        }

    }
}